#include <iostream>
#include <unordered_map>
#include <utility>
#include <vector>
#include <queue>
using namespace std;
// 这里简要介绍一下这里的逻辑上的误区，就是我们在跳跃的是后不能是反复跳跃的，一定是入口一次，出口一次，这样才不会导致一些意想不到的错误。
typedef pair<int, int> PII;
queue<PII> q;
vector<string> nums;
const int N = 310;
int flag[N][N] = {0};
int n, m;
int dx[4] = {0, -1, 0, 1};
int dy[4] = {1, 0, -1, 0};
PII t[N][N];
int ans[N][N];
int ret = 0x3f3f3f3f;
unordered_map<char, PII> h;
int main() {
    cin >> n >> m;
    for(int i = 0; i < n; i++) {
        string s;
        cin >> s;
        nums.push_back(s);
    }
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            if(nums[i][j] == '@') {
                q.push({i, j});
                flag[i][j] = 1;
            }
            if(nums[i][j] >= 'A' && nums[i][j] <= 'Z') {
                if(h.find(nums[i][j]) == h.end()) {
                    h.insert({nums[i][j], make_pair(i, j)});
                }else {
                    t[i][j] = h[nums[i][j]];
                    auto&[l, r] = h[nums[i][j]];
                    t[l][r] = make_pair(i, j);
                }
            }
        }
    }
    while(!q.empty()) {
        auto& [a, b] = q.front();
        q.pop();
        for(int i = 0; i < 4; i++) {
            int x = a + dx[i], y = b + dy[i];
            if(x >= 0 && x < n && y >= 0 && y < m && nums[x][y] != '#' && nums[x][y] != '@') {
                if(nums[x][y] == '=') {
                    ans[x][y] = ans[a][b] + 1;
                    cout << ans[x][y] << endl;
                    return 0;
                }
                int tx = x, ty = y;
                if(nums[x][y] <= 'Z' && nums[x][y] >= 'A') {;
                    tx = t[x][y].first;
                    ty = t[x][y].second;
                }
                if(flag[tx][ty] == 1) {
                    continue;
                }
                flag[tx][ty] = 1;
                ans[tx][ty] = ans[a][b] + 1;
                q.push({tx, ty});
            }
        }
    }
    return 0;
}


// #include <iostream>
// #include <vector>
// #include <queue>
// #include <unordered_map>
// #include <utility>
// using namespace std;

// const int N = 310;
// int n, m;
// vector<string> grid;
// int dist[N][N];
// bool visited[N][N] = {false};
// pair<int, int> other[N][N];
// int dx[4] = {0, -1, 0, 1};
// int dy[4] = {1, 0, -1, 0};

// int main() {
//     cin >> n >> m;
//     grid.resize(n);
//     int sx, sy;
//     for (int i = 0; i < n; i++) {
//         cin >> grid[i];
//         for (int j = 0; j < m; j++) {
//             if (grid[i][j] == '@') {
//                 sx = i;
//                 sy = j;
//             }
//         }
//     }

//     for (int i = 0; i < n; i++) {
//         for (int j = 0; j < m; j++) {
//             other[i][j] = {-1, -1};
//         }
//     }

//     unordered_map<char, vector<pair<int, int>>> mp;
//     for (int i = 0; i < n; i++) {
//         for (int j = 0; j < m; j++) {
//             if (grid[i][j] >= 'A' && grid[i][j] <= 'Z') {
//                 mp[grid[i][j]].push_back({i, j});
//             }
//         }
//     }
//     for (auto &[ch, points] : mp) {
//         if (points.size() == 2) {
//             auto p1 = points[0];
//             auto p2 = points[1];
//             other[p1.first][p1.second] = p2;
//             other[p2.first][p2.second] = p1;
//         }
//     }

//     queue<pair<int, int>> q;
//     q.push({sx, sy});
//     visited[sx][sy] = true;
//     dist[sx][sy] = 0;

//     while (!q.empty()) {
//         auto [x, y] = q.front();
//         q.pop();
//         for (int i = 0; i < 4; i++) {
//             int nx = x + dx[i], ny = y + dy[i];
//             if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
//             if (grid[nx][ny] == '#') continue;

//             int tx = nx, ty = ny;
//             if (grid[nx][ny] >= 'A' && grid[nx][ny] <= 'Z') {
//                 auto [ox, oy] = other[nx][ny];
//                 if (ox != -1 && oy != -1) {
//                     tx = ox;
//                     ty = oy;
//                 }
//             }

//             if (visited[tx][ty]) continue;
//             visited[tx][ty] = true;
//             dist[tx][ty] = dist[x][y] + 1;
//             if (grid[tx][ty] == '=') {
//                 cout << dist[tx][ty] << endl;
//                 return 0;
//             }
//             q.push({tx, ty});
//         }
//     }

//     return 0;
// }